package cn.alcatraz.basic.service.impl;

import cn.alcatraz.basic.constant.BaseConstant;
import cn.alcatraz.basic.dto.SmsCodeDto;
import cn.alcatraz.basic.exception.BusinessException;
import cn.alcatraz.basic.service.IVerifyCodeService;
import cn.alcatraz.basic.utils.StrUtils;
import cn.alcatraz.basic.utils.VerifyCodeUtil;

import cn.alcatraz.user.domain.User;
import cn.alcatraz.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import static cn.alcatraz.basic.constant.BaseConstant.VerifyCodeConstant.GET_SMS_OVERTIME;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public String getImageCode(String imageCodeKey) throws IOException {
        // 1.判断参数是否为空
        if (StringUtils.isEmpty(imageCodeKey)) {
            throw new BusinessException("参数不能为空，请传递正确参数！");
        }
        // 2.获取到随机4位字符串
        String imageCode = StrUtils.getComplexRandomString(4);
        // 3.使用工具类生成Base64图形验证码字符串
        String imageBase64Str = VerifyCodeUtil.VerifyCode(100, 30, imageCode);
        // 4.根据key、value保存到Redis中，并设置三分钟有效
        redisTemplate.opsForValue().set(imageCodeKey, imageCode, 5, TimeUnit.MINUTES);
        return imageBase64Str;
    }

    /**
     * @Title: smsCode
     * @Description: 发送图片验证码
     * @Author: Alcatraz
     * @Version: 1.0
     * @Date: 2022/7/10 18:48
     * @Parameters: [smsCodeDto]
     * @Return void
     */
    @Override
    public void smsCode(SmsCodeDto smsCodeDto) {
        // 获取参数
        String phone = smsCodeDto.getPhone();

        // 业务类型type
        String type = smsCodeDto.getType();
        //1.非空校验
        if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(type)) {
            throw new BusinessException("参数不能为空！");
        }
        // 2.判断是走那个业务方法
        // 2.1.注册业务
        if ("register".equals(type)) {
            // 校验图形验证码是否正确
            checkImageCode(smsCodeDto);
            //3.判断用户是否已注册，如果已注册提示用户
            User user = userMapper.loadByPhone(phone);
            if (user != null) {
                throw new BusinessException("用户已注册，请直接登录.");
            }
            sendCode(BaseConstant.VerifyCodeConstant.BUSINESS_REGISTER_KEY, phone);
        } else if ("binder".equals(type)) { // 2.2.微信绑定账号业务,发送短信验证码
            sendCode(BaseConstant.VerifyCodeConstant.BUSINESS_BINDER_KEY, phone);
        }
    }

    /**
     * @Title: sendCode
     * @Description: 发送手机验证码
     * @Author: Alcatraz
     * @Version: 1.0
     * @Date: 2022/7/10 18:52
     * @Parameters: [businessKey, phone]
     * @Return void
     */
    public void sendCode(String businessKey, String phone) {
        //根据电话号码拼接业务键，去redis中获取对应的value值，判断是否存在
        String phoneCodeKey = businessKey + phone;
        Object phoneCodeValue = redisTemplate.opsForValue().get(phoneCodeKey);
        //定义一个空字符串，专门用来接收验证码
        String phoneCode = "";
        if (phoneCodeValue == null) {//1.不存在
            //生成新的随机验证码,并赋值给空字符串
            phoneCode = StrUtils.getComplexRandomString(6);
        } else {
            //分割value得到时间戳，跟现在的时间戳做减法，如果小于1分钟的毫秒数抛出异常
            String[] phoneCodeValueTmp = phoneCodeValue.toString().split(":");
            //之前存入code时，我们记录的时间戳
            Long oldTime = Long.valueOf(phoneCodeValueTmp[0]);
            //现在的时间戳
            Long nowTime = System.currentTimeMillis();
            if (nowTime - oldTime < GET_SMS_OVERTIME) {
                throw new BusinessException("请一分钟之后再获取！");
            }
            //将旧的验证码赋值给空字符串
            phoneCode = phoneCodeValueTmp[1];
        }
        //通过业务键+phone作为key，验证码+时间戳作为value，存入redis，设置为五分钟有效
        String phoneCodeRedis = System.currentTimeMillis() + ":" + phoneCode;
        redisTemplate.opsForValue().set(phoneCodeKey, phoneCodeRedis, 5, TimeUnit.MINUTES);
        //发送短信验证码
        // SmsUtils.sendCode(phone, "您的验证码是："+ phoneCode);
        System.out.println("您的验证码是：" + phoneCode);
    }

    /**
     * @Title: checkImageCode
     * @Description: 校验图片验证码
     * @Author: Alcatraz
     * @Version: 1.0
     * @Date: 2022/7/10 18:49
     * @Parameters: [smsCodeDto]
     * @Return void
     */
    public void checkImageCode(SmsCodeDto smsCodeDto) {
        // 图形验证码的key
        String imageCodeKey = smsCodeDto.getImageCodeKey();
        // 图形验证码的value
        String imageCodeValue = smsCodeDto.getImageCodeValue();
        //1.非空校验
        if (StringUtils.isEmpty(imageCodeKey) || StringUtils.isEmpty(imageCodeValue)) {
            throw new BusinessException("参数不能为空！");
        }
        //2.判断图形验证码是否正确以及存在
        Object imageCodeValueTmp = redisTemplate.opsForValue().get(imageCodeKey);
        if (imageCodeValueTmp == null) {
            throw new BusinessException("验证码已过期，请重新获取！");
        }
        // 忽略大小写比较图形验证码是否正确
        if (!imageCodeValueTmp.toString().equalsIgnoreCase(imageCodeValue)) {
            throw new BusinessException("验证码错误，请重新输入！");
        }
    }
    
        /*//获取参数
        String getPhone = smsCodeDto.getPhone();
        //图形验证码的key
        String getImageCodeKey = smsCodeDto.getImageCodeKey();

        //图形验证码的value
        String getImageCodeValue = smsCodeDto.getImageCodeValue();
        //非空校验
        if(StringUtils.isEmpty(getPhone)){
            throw new BusinessException("手机号不能为空");
        }
        //判断图形验证码是否正确以及存在
        Object tempImageCodeValue = redisTemplate.opsForValue().get(getImageCodeKey);
        //忽略大小写比较图形验证码是否正确
        if(!tempImageCodeValue.toString().equalsIgnoreCase(getImageCodeValue)){
            throw new BusinessException("图形验证码不正确,请重新输入");
        }
        //判断用户是否已注册，如果已注册提示用户
        User user = userMapper.loadByPhone(getPhone);
        if(user != null){
            throw new BusinessException("该用户已注册");
        }
        //根据电话号码常量，去redis中获取对应的value值，判断是否存在
        String verifycodeExist = BaseConstant.VerifyCodeConstant.BUSINESS_REGISTER_KEY + getPhone;
        Object valueOfPhoneCode = redisTemplate.opsForValue().get(verifycodeExist);

        //定义一个空字符串，专门用来接收验证码
        String phoneCode = "";
        //生成新的随机验证码,并赋值给空字符串
        if(valueOfPhoneCode == null){
             phoneCode = StrUtils.getComplexRandomString(6);
        }else{
            //分割value得到时间戳，跟现在的时间戳做减法，如果小于1分钟的毫秒数抛出异常
            String[] splitPhoneCode = valueOfPhoneCode.toString().split(":");
            //之前存入code时，我们记录的时间戳
            Long oldTimeCode = Long.valueOf(splitPhoneCode[0]);
            //现在的时间戳
            long nowTheTime = System.currentTimeMillis();
            if(nowTheTime - oldTimeCode < GET_SMS_OVERTIME){
                throw new BusinessException("请勿重复获取,一分钟后重试");
            }
            //将旧的验证码赋值给空字符串
            phoneCode = splitPhoneCode[1];


        }
        //通过业务键+phone作为key，验证码+时间戳作为value，存入redis，设置为三分钟有效
        String phoneCodeRedis = System.currentTimeMillis() + ":" + phoneCode;
        redisTemplate.opsForValue().set(verifycodeExist,phoneCodeRedis,5,TimeUnit.MINUTES);
        //发送短信验证码
        // SmsUtils.sendCode(phone, "亲，您的验证码是："+ phoneCode);
        System.out.println("手机验证码是"+ phoneCode);
    }*/


    @Override
    public void emailCode(SmsCodeDto smsCodeDto) {

        // 获取参数
        String getEmail = smsCodeDto.getEmail();

        // 业务类型type
        String getImageCodeKey = smsCodeDto.getImageCodeKey();

        //图形验证码的value
        String getImageCodeValue = smsCodeDto.getImageCodeValue();
        //非空校验
        if (StringUtils.isEmpty(getEmail)) {
            throw new BusinessException("邮箱不能为空");
        }
        //判断图形验证码是否正确以及存在
        Object tempImageCodeValue = redisTemplate.opsForValue().get(getImageCodeKey);
        //忽略大小写比较图形验证码是否正确
        if (!tempImageCodeValue.toString().equalsIgnoreCase(getImageCodeValue)) {
            throw new BusinessException("图形验证码不正确,请重新输入");
        }
        //判断用户是否已注册，如果已注册提示用户
        User user = userMapper.loadByPhone(getEmail);
        if (user != null) {
            throw new BusinessException("该用户已注册");
        }
        //根据邮箱号码常量，去redis中获取对应的value值，判断是否存在
        String verifycodeExist = BaseConstant.VerifyCodeConstant.BUSINESS_REGISTER_KEY + getEmail;
        Object valueOfPhoneCode = redisTemplate.opsForValue().get(verifycodeExist);

        //定义一个空字符串，专门用来接收验证码
        String emailCode = "";
        //生成新的随机验证码,并赋值给空字符串
        if (valueOfPhoneCode == null) {
            emailCode = StrUtils.getComplexRandomString(6);
        } else {
            //分割value得到时间戳，跟现在的时间戳做减法，如果小于1分钟的毫秒数抛出异常
            String[] splitEmailCode = valueOfPhoneCode.toString().split(":");
            //之前存入code时，我们记录的时间戳
            Long oldTimeCode = Long.valueOf(splitEmailCode[0]);
            //现在的时间戳
            long nowTheTime = System.currentTimeMillis();
            if (nowTheTime - oldTimeCode < GET_SMS_OVERTIME) {
                throw new BusinessException("请勿重复获取,一分钟后重试");
            }
            //将旧的验证码赋值给空字符串
            emailCode = splitEmailCode[1];


        }
        //通过业务键+phone作为key，验证码+时间戳作为value，存入redis，设置为三分钟有效
        String phoneCodeRedis = System.currentTimeMillis() + ":" + emailCode;
        redisTemplate.opsForValue().set(verifycodeExist, phoneCodeRedis, 5, TimeUnit.MINUTES);
        //发送短信验证码
        System.out.println("邮箱验证码是" + emailCode);
    }
}
        /*
        //根据电话号码拼接业务键，去redis中获取对应的value值，判断是否存在
        String emailCodeKey = businessKey + email;
        Object emailCodeValue = redisTemplate.opsForValue().get(emailCodeKey);
        //定义一个空字符串，专门用来接收验证码
        String emailCode = "";
        if (emailCodeValue == null){//1.不存在
            //生成新的随机验证码,并赋值给空字符串
            emailCode = StrUtils.getComplexRandomString(6);
        }else {
            //分割value得到时间戳，跟现在的时间戳做减法，如果小于1分钟的毫秒数抛出异常
            String[] emailCodeValueTmp = emailCodeValue.toString().split(":");
            //之前存入code时，我们记录的时间戳
            Long oldTime = Long.valueOf(emailCodeValueTmp[0]);
            //现在的时间戳
            Long nowTime = System.currentTimeMillis();
            if (nowTime - oldTime < GET_SMS_OVERTIME){
                throw new BusinessException("请一分钟之后再获取！");
            }
            //将旧的验证码赋值给空字符串
            emailCode = emailCodeValueTmp[1];
        }
        //通过业务键+phone作为key，验证码+时间戳作为value，存入redis，设置为五分钟有效
        String emailCodeRedis = System.currentTimeMillis() + ":" + emailCode;
        redisTemplate.opsForValue().set(emailCodeKey, emailCodeRedis, 5, TimeUnit.MINUTES);
        //发送短信验证码
        System.out.println("您的验证码是："+ emailCode);
    }*/





